using System;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;

namespace DBRestriker.Data
{
	class TableFilter
	{
		private readonly Regex _multiLikeRegEx;
		private readonly string _multiLikePattern = string.Format(@"(?<{0}>[^{2}]+)(?<{1}>{2}+)|(?<{1}>{2}+)(?<{0}>[^{2}]+)", VALUE_GROUPNAME, OPERATOR_GROUPNAME, WILDCARD);
		private const string VALUE_GROUPNAME = "Value";
		private const string OPERATOR_GROUPNAME = "Operator";
		private const string WILDCARD = "%";

		internal TableFilter()
		{
			_multiLikeRegEx = new Regex(_multiLikePattern);
		}

		internal string GetFilterExpression(DataGridViewRow row, SearchMode searchMode)
		{
			StringBuilder filter = new StringBuilder();
			foreach (DataGridViewCell filterCell in row.Cells)
			{
				string filterValue = string.Format("{0}", filterCell.Value);
				if (0 < filterValue.Length)
				{
					switch (searchMode)
					{
						case SearchMode.Instring:
							filterValue = string.Format("{0}{1}{2}", WILDCARD, filterValue, WILDCARD);
							break;
						case SearchMode.Prefix:
							filterValue = string.Format("{0}{1}", filterValue, WILDCARD);
							break;
					}

					string columnName = filterCell.OwningColumn.Name;
					if (_multiLikeRegEx.IsMatch(filterValue))
					{
						// Replace inner wildcards with multi statements e.g.: prefix%suffix => prefix% AND %suffix
						string[] tokens = filterValue.Split(new string[] {WILDCARD}, StringSplitOptions.RemoveEmptyEntries);
						for (int index = 0, count = tokens.Length; index < count; index++)
						{
							string value = tokens[index];
							string startOp = (0 < index || filterValue.StartsWith(WILDCARD)) ? WILDCARD : string.Empty;
							string endOp = (index < count - 1 || filterValue.EndsWith(WILDCARD)) ? WILDCARD : string.Empty;
							string multiFilterValue = string.Format("{0}{1}{2}", startOp, value, endOp);
							AppendFilterValue(filter, columnName, multiFilterValue);
						}
					}
					else
					{
						AppendFilterValue(filter, columnName, filterValue);
					}
				}
			}
			return filter.ToString();
		}

		private static void AppendFilterValue(StringBuilder filter, string columnName, string filterValue)
		{
			if (filter.Length < 1)
			{
				filter.AppendFormat("{0} LIKE '{1}'", columnName, filterValue);
			}
			else
			{
				filter.AppendFormat(" AND {0} LIKE '{1}'", columnName, filterValue);
			}
		}
	}
}